Examen C++ 2024 — 2025 · GIA FA
Quatre exercices avec corrigé partiel intégré au PDF : passage de paramètres, classe Image (surcharge operator[]), polymorphisme (Polygone / Rectangle / override), simulation des urgences d'un hôpital avec priority_queue STL.
i. Sujet & corrigé partiel
Le corrigé est intégré directement dans le PDF (en violet sous chaque question). Le sujet et la correction partagent le même document.
ii. Notions mobilisées
| Exo | Sujet | Notion clé | Chapitre |
|---|---|---|---|
| 1 | Passage de paramètres (int c, int *c, int &c) | Valeur, pointeur, référence | SE1 |
| 2 | Classe Image (short** a) | Constructeur de copie, opérateur =, règle de trois | SE2 §5 |
static short& operator[](int i) | Surcharge de [] renvoyant une référence, static | SE3 | |
| 3 | Polygone / Rectangle avec virtual et override | Polymorphisme dynamique, signatures correctes | SE4 §6 |
| 4 | Simulation urgences hôpital | Classe abstraite Objet (virtuelle pure), héritage | SE4 §7 |
priority_queue + foncteur de comparaison + exceptions | STL, foncteurs, try/catch sur saisie | SE7 · SE6 |
iii. Repères de correction
Exercice 1 — Passage de paramètres (2 pts)
Pour void ajouter(int a, int b, int c) { c = a+b; } sur ajouter(1, -2, 0) :
- (a) par valeur :
c = 0dans le main (la modification reste locale) - (c) par référence (
int &c) :c = -1dans le main (alias direct, la modification est visible)
Appellations : copie de valeur pour a, b · copie de référence pour le cas (c).
Exercice 2 — Classe Image (6 pts)
class Image {
short** a;
int nlignes, ncols;
public:
Image();
Image(int m, int n);
Image(const Image&); // constructeur de copie
Image& operator=(const Image&); // affectation
~Image();
static short& operator[](int i) { return a[i]; }
};
- Q1-Q4 : expliquer chaque méthode (constructeur, copy-ctor, operator=, destructeur). Cf. règle de trois — toute classe qui gère de la mémoire dynamique (
new) doit définir les trois. - Q5 : la classe est-elle canonique ? Oui si les 4 méthodes sont présentes et corrigées : ctor par défaut, ctor de copie,
operator=, destructeur. Le sujet en demande la justification. - Q6 :
operator[]est un opérateur de surcharge d'indice.short&renvoie une référence versa[i], ce qui permet d'écrireimg[3] = 42. - Q7 : le mot-clé
staticindique que la méthode est une méthode de classe, pas d'instance. Discutable ici (l'operator[]a besoin d'accéder àa) — le sujet pose la question pour faire réfléchir au problème.
Exercice 3 — Polymorphisme (4 pts)
Code donné : hiérarchie Polygone → Rectangle avec une série de méthodes virtuelles, certaines redéclarées avec override.
class Polygone {
virtual void perimetre();
virtual void aire() const;
virtual void tauxOccupation(int = 0);
void espaceDiponible();
};
class Rectangle : public Polygone {
virtual void perimetre();
virtual void aire();
virtual void perimetre() override; // ligne 17
virtual void tauxOccupation(double = 0.0);
virtual void aire() override; // ligne 19
virtual void tauxOccupation(double = 0.0) override; // ligne 20
void espaceDiponible() override; // ligne 21
};
Lignes 15-21 : justes ou fausses ?
- L15
virtual void perimetre();: juste — redéclaration valide d'une méthode virtuelle de la base, le polymorphisme fonctionne. - L16
virtual void aire();: fausse — la base aaire() const, la fille perd leconstdonc signature différente = nouvelle méthode (pas un override). Compile mais ne polymorphe pas. - L17
perimetre() override;: erreur de compilation —perimetreest déjà déclarée à L15, double déclaration. - L18-19-20 : redéclarations multiples, ambiguës.
- L21
espaceDiponible() override;: erreur — la basePolygone::espaceDiponiblen'est pas virtuelle, on ne peut pas la marqueroverride.
override demande au compilateur de vérifier qu'on redéfinit bien une méthode virtuelle existante avec la même signature exacte. Toute divergence (const, type de paramètre, méthode non virtuelle dans la base) déclenche une erreur. C'est précieux pour éviter les bugs silencieux.
Exercice 4 — Urgences hôpital avec priority_queue (8 pts)
Programme complet à fournir (4 fichiers). Structure :
// objet.h — classe abstraite (1 pt)
class Objet {
public:
virtual void afficher() = 0;
};
// malade.cpp — hérite d'Objet (3 pts)
#include "objet.h"
class Malade : public Objet {
int id, gravite;
public:
Malade(int _id, int _gr) : id(_id), gravite(_gr) {}
virtual void afficher() override {
cout << "id=" << id << " gravite=" << gravite;
}
};
// comparaison.cpp — foncteur
class Comparaison {
public:
bool operator()(const Malade& m1, const Malade& m2) {
return m1.priority < m2.priority;
}
};
// filegravitemalade.cpp — héritage + STL (4 pts)
class FileGraviteMalades : public Objet {
public:
priority_queue<Malade, vector<Malade>, Comparaison> gq;
virtual void afficher() override {
Malade m;
auto gq_temp = gq;
while (!gq_temp.empty()) {
m = gq_temp.top();
m.afficher();
gq_temp.pop();
}
}
};
Main avec saisie sécurisée par exception (saisirInt avec throw/catch) :
int saisirInt(string message, int NM, int min, int max) {
int a;
while (1) {
try {
cout << message << NM << " entre : " << min << " et " << max;
cin >> a;
cin.clear(); // reset eventual fail bits
if (a < min || a > max) throw(10);
return a;
} catch (int b) {
cout << "erreur de saisie" << endl;
}
}
}
int main(int argc, char** argv) {
int nbMalades = atoi(argv[1]);
FileGraviteMalades fgm;
for (int i = 0; i < nbMalades; i++) {
int gravite = saisirInt("entrer la gravité du malade : ", i + 1, 1, 5);
Malade m(i + 1, gravite);
fgm.gq.push(m);
}
while (!fgm.gq.empty()) { // traiter par gravité décroissante
cout << fgm.gq.top() << endl;
fgm.gq.pop();
}
return 0;
}
Compilation : g++ *.cpp -Wall -o gestionUrgence · Exécution : ./gestionUrgence 6.
★ Notions ré-activées
- Passage par valeur / pointeur / référence :
void f(int c)vsvoid f(int* c)vsvoid f(int& c) - Règle de trois : ctor de copie +
operator=+ destructeur dès qu'il y a dunew - Surcharge
operator[]avec retourT&pour permettre l'écriture indexée - Classe abstraite avec
virtual void m() = 0 overrideexige une signature exacte (mêmeconst, mêmes types)- On ne peut pas
overrideune méthode non-virtuelle de la base priority_queue<T, vector<T>, Comparator>avec foncteuroperator()top()+pop()pour dépiler le plus prioritaire- Saisie sécurisée :
try { cin>>a; if (...) throw; } catch (int)